在Unity中使用Protobuf-net

Protobuf-net可以通过C#脚本直接序列化与反序列化

一、Protobuf-net安装

  1、新建VS控制台项目。

  2、选择项目,右键菜单选择“管理NuGet程序包”。

  3、浏览 -> Protobuf-net -> 安装。

    安装后,在项目的同级目录会生成 packages文件夹。

  4、拷贝protobuf-net.dll到Unity中。

    1)、确认Unity中使用的.NET版本。     Editor菜单 -> PlayerSettings -> Player -> Other Settings -> Scripting Runtime Version -> Stable (.NET 3.5 Equivalent)

    2)、根据Unity中使用的.NET版本,拷贝packages/protobuf-net.2.4.0/lib/net35/protobuf-net.dll到Unity中。

二、示例

    /*
     *   Author : shenjun
     */

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.IO;
    #if UNITY_EDITOR
    using UnityEditor;
    #endif

    public class LessonProtobuf_CSharpFile : MonoBehaviour {

        string filePath { get { return Application.streamingAssetsPath + "/ProtobufData/"; } }

        void Start () {

            PlayerInfo playerInfo = new PlayerInfo();
            playerInfo.id = 1;
            playerInfo.name = "shenjun";
            playerInfo.listInfo = new List<string>
            {
                "a", "b", "c"
            };
            playerInfo.dicInfo = new Dictionary<int, string>();
            playerInfo.dicInfo.Add(1, "zhangsan");
            playerInfo.dicInfo.Add(2, "lisi");
            playerInfo.dicInfo.Add(3, "wangwu");

            // 序列化
            using (FileStream stream = File.OpenWrite(filePath + "test.dat"))
            {
                ProtoBuf.Serializer.Serialize(stream, playerInfo);
            }

    #if UNITY_EDITOR
            AssetDatabase.Refresh();
    #endif

            // 反序列化
            using (FileStream stream = File.OpenRead(filePath + "test.dat"))
            {
                PlayerInfo info = ProtoBuf.Serializer.Deserialize<PlayerInfo>(stream);
                Debug.Log(info.name);
            }
        }
    }

    [ProtoBuf.ProtoContract] //表示这个类要作为ProtoBuf数据格式来进行传输
    public class PlayerInfo
    {
        [ProtoBuf.ProtoMember(1)]  // 必须选择一个整数来标识每个成员
        public int id;

        [ProtoBuf.ProtoMember(2)]
        public string name;

        [ProtoBuf.ProtoMember(3)]
        public List<string> listInfo;

        [ProtoBuf.ProtoMember(4)]
        public Dictionary<int, string> dicInfo;
    }

  

三、标识符说明

  • 它们必须是正整数

  • 它们在单个类型中必须是唯一的,但如果启用了继承,则可以在子类型中重复使用相同的数字

  • 标识符不得与任何继承标识符冲突(稍后讨论)

  • 较低的数字占用较少的空间 - 不要启动100,000,000

  • 标识符很重要; 您可以更改成员名称,或在属性和字段之间切换它,但更改标识符会更改数据

  

四、类型说明

  支持的:

    自定义类:
        被标记为ProtoBuf.ProtoContract
        有一个无参数的构造函数
        public的
    单维数组:T []
    List / IList
    Dictionary <TKey,TValue> / IDictionary <TKey,TValue>
    任何实现IEnumerable并具有Add(T)方法的类型
    不支持自定义结构。

五、高级主题

  1、继承

  必须以类似的方式显式声明继承,如果必须用于XmlSerializer和DataContractSerializer。这是通过[ProtoInclude(...)]在已知子类型的每种类型上完成的:

    [ProtoContract]
    [ProtoInclude(7, typeof(SomeDerivedType))]
    class SomeBaseType {...}

    [ProtoContract]
    class SomeDerivedType {...}

  上述7没有特别的意义;它是一个整数键,就像每个[ProtoMember(...)]一样。它在SomeBaseType方面必须是唯一的(SomeBaseType中没有其他[ProtoInclude(...)][ProtoMember(...)]可以使用7),但不需要全局唯一。

  2、.proto文件

  作为编写类和装饰它们的替代方法,您可以使用.proto模式生成类型protogen; 该protogen工具可从该位置以zip形式提供,或作为“全局工具”(多平台)提供。

注:.proto使用Proto2语法

  

🔚